#include <iostream>
#include <pthread.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <thread>
#include <string>

using namespace std;

__thread int shared_value = 100;

//转化为十六进制
string toHex(pthread_t tid)
{
    //每个线程都会为buffer创建一个独立的栈帧
    char buffer[64];//这里是临时空间，所以这个函数是安全的
    snprintf(buffer,sizeof(buffer),"0x%lx",tid);
    return buffer;
}


void *start(void* args)
{
    string name = static_cast<const char*>(args);
    while(true)
    {
        //打印id和name
        printf("this is new thread, name:%s,shared_value:%d,&shared_value:%p\n",name.c_str(),shared_value,&shared_value);
        sleep(1);
    }
}
int main()
{
    pthread_t tid;
    pthread_create(&tid,nullptr,start,(void*)"thread-1");
    cout << "I am a main thread" << ",thread ID:" << toHex(pthread_self()) << endl;
    while(true)
    {
        cout<<"this is main thread"<<",sahred_value:"<<shared_value<<"&shared_value"<<&shared_value<<endl;
        sleep(1);
    }
    pthread_join(tid,nullptr);
    return 0;
}


// int *addr = nullptr;
// void* start(void* args)
// {
//     //是否可以在新线程中进行fork()？-----答案是可以的---但是默认形成的新进程只有一个pcb
//     pid_t id = fork();
//     if(id == 0)
//     {
//         //
//     }
//     // //自己将自己分离
//     // //pthread_detach(pthread_self());
//     // string name = static_cast<const char*>(args);
//     // int a = 100;
//     // addr = &a;
//     // while(true)
//     // {
//     //     //cout << name << "local val a:" << a << endl;
//     //     cout<<"I am a new thread"<<endl;
//     //     sleep(1);
//     //     //break;
//     // }
//     // //return 0;//新线程退出表示该线程结束
//     // //exit(1);//可以在新线程中调用exit函数吗？----任何地方调用exit表示进程退出
    
//     // pthread_exit((void*)1);//pthread_exit和return是等价的
// }


// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid,nullptr,start,(void*)"thread-1");

//     pthread_detach(tid);
//     //sleep(5);

//     //int n = pthread_cancel(tid);
//     //cout<<"cancel thread:"<<tid<<endl;

//     sleep(5);

//     void *ret = nullptr;
//     int n = pthread_join(tid,&ret);//PTHREAD_CANCELED;
//     cout<< "new thread exit code: " << (long long int)ret << ",n:" << n << endl;

//     //pthread_create(&tid2,nullptr,start2,(void*)"thread-2");

//     return 0;//主线程return表进程结束
// }

// class ThreadData
// {
// public:
//     ThreadData()
//     {}
//     void Init(const string& name,int a,int b)
//     {
//         _name = name;
//         _a = a;
//         _b = b;
//     }
//     int Excute()
//     {
//         _result = _a+_b;
//     }
//     //将线程id保存起来
//     void SetId(pthread_t tid){_tid = tid;}
//     //获取对应的线程的tid
//     pthread_t Gettid(){return _tid;}
//     int Result(){return _result;}
//     int A(){return _a;}
//     int B(){return _b;}
//     ~ThreadData(){}
//     string Name()
//     {
//         return _name;
//     }
// private:
//     string _name;
//     int _a;
//     int _b;
//     int _result;
//     pthread_t _tid;
// };

// //全局变量在线程内部是共享的
// int gval = 0;

// //所有线程都能看到所有方法，代码是共享的

// //转化为十六进制
// string toHex(pthread_t tid)
// {
//     //每个线程都会为buffer创建一个独立的栈帧
//     char buffer[64];//这里是临时空间，所以这个函数是安全的
//     snprintf(buffer,sizeof(buffer),"0x%lx",tid);
//     return buffer;
// }

// //一个线程一旦出了问题，所有线程都会崩溃
// void* routine(void *args)
// {
//     ThreadData* td = static_cast<ThreadData*>(args);
//     while(true)
//     {
//         //打印name和tid
//         //不加保护的情况下，显示器文件就是共享资源，显示器文件会出现错乱打印属于正常现象
//         cout<<"I'm new thread,my name is:"<<td->Name()<<",my tid:"<<toHex(pthread_self())<<",Global variables:"<<gval<<endl;
//         gval++;
//         td->Excute();
//         sleep(1);
//         break;
//     }
//     //int *p = new int(10);
//     //谁拿着堆空间的入口地址，谁就可以访问堆区
//     return (void*)td;//线程退出方式1：线程入口函数，return，表示线程退出
// }

// #define Num 10
// int main()
// {
//     //其实栈区不算共享，但是如果想看是可以看到的


//     // ThreadData td[Num];
//     // for(int i = 0;i < Num;i++)
//     // {
//     //     char id[64];
//     //     snprintf(id,sizeof(id),"thread-%d",i);
//     //     td[i].Init(id,i*10,i*20);//初始化
//     // }
//     // for(int i = 0;i < Num;i++)
//     // {
//     //     pthread_t id;
//     //     pthread_create(&id,nullptr,routine,&td[i]);
//     //     td[i].SetId(id);//将线程id，set进结构体数组当中
//     // }

//     // //等待多个线程
//     // for(int i = 0;i < Num;i++)
//     // {
//     //     pthread_join(td[i].Gettid(),nullptr);
//     // }
    
//     // //汇总处理：
//     // for(int i = 0;i < Num;i++)
//     // {
//     //     printf("td[%d]:%d+%d=%d[%ld]\n",i,td[i].A(),td[i].B(),td[i].Result(),td[i].Gettid());
//     // }

//     //新线程和主线程谁先运行，并不确定
//     //线程创建出来，要对进程的时间片进行瓜分

//     //创建线程的传参问题和等待线程的返回值问题
//     // pthread_t tid1;
//     // ThreadData *td = new ThreadData("thread-1",10,20);
//     // pthread_create(&tid1,nullptr,routine,td);//传递对象进去，不建议传递临时对象


//     // //线程创建之后，也是要被等待和退出的（线程和进程一样，也是要被等待和回收的）
//     // //如何获得线程的退出结果
//     // void* ret = nullptr;
//     // ThreadData* red = nullptr;
//     // int n = pthread_join(tid1,(void**)&red);
//     // cout<<red->Result()<<endl;
//     // if(n != 0)
//     // {
//     //     //打印错误信息，将错误码转化为错误。
//     //     cerr<<"join error:"<<n<<strerror(n)<<endl;
//     //     return 1;
//     // }
//     // cout<<"join sucess"<<endl;

//     // pthread_t tid2;
//     // pthread_create(&tid2,nullptr,routine,(void*)"thread-2");

//     // pthread_t tid3;
//     // pthread_create(&tid3,nullptr,routine,(void*)"thread-3");

//     // pthread_t tid4;
//     // pthread_create(&tid4,nullptr,routine,(void*)"thread-4");

//     //线程虽然是库提供的但是，但是底层还是LWP
//     //cout<<"new thread id:"<<tid<<endl;//当走到下面的时候能保证tid是一定被创建出来的
//     // printf("new thread id:0x%lx\n",tid1);
//     // // printf("new thread id:0x%lx\n",tid2);
//     // // printf("new thread id:0x%lx\n",tid3);
//     // // printf("new thread id:0x%lx\n",tid4);
//     // while(true)
//     // {
//     //     cout<<"I'm main thread"<<endl;
//     //     sleep(1);
//     // }
//     return 0;
// }








// // void* routine(void *args)
// // {
// //     string name = static_cast<const char*>(args);
// //     while(true)
// //     {
// //         cout<<"I'm new thread,my name is:"<<name<<endl;
// //         sleep(1);
// //     }
// // }

// // int main()
// // {
// //     thread t
// //     ([]()
// //     {
// //         while(true)
// //         {
// //             cout<<"I'm new thread,my name is:new thread"<<endl;
// //             sleep(1);
// //         }
// //     });
// //     while(true)
// //     {
// //         cout<<"I'm main thread,my name is:main thread"<<endl;
// //         sleep(1);
// //     }
// //     // pthread_t tid;
// //     // int n = pthread_create(&tid,nullptr,routine,(void*)"thread-1");
// //     // if(n != 0)
// //     // {
// //     //     cout<<"create thread error:"<<strerror(n)<<endl;
// //     // }
// //     // while(true)
// //     // {
// //     //     cout<<"I'm main thread"<<endl;
// //     //     sleep(1);
// //     // }
// //     // return 0;
// // }